View Port Properties
The interface to view port objects is entirely procedural. You manipulate the information in a view port by modifying its properties using QuickDraw GX functions.View port objects have nine accessible properties, as shown in Figure 7-2. Note that, because a view port is an object and not a data structure, the order of the properties as shown in Figure 7-2 is completely arbitrary. Properties in italics are references to other objects.
Figure 7-2 View port object properties
These are the accessible properties of a view port:
QuickDraw GX provides functions to manipulate each of these view port object properties.
- Clip. A specialized shape geometry that controls the visibility of all shapes drawn to this view port. Only the parts of shapes that overlap with the clip remain visible when they are drawn. In the porthole analogy for a view port, the view port clip represents the transparent area of the porthole. The view port clip is further described in the next section, "View Port Clip and Mapping."
- Mapping. A mathematical matrix that specifies the translation, scaling, skewing, rotation, and perspective of all shapes drawn to this view port. The view port mapping is further described in the next section, "View Port Clip and Mapping."
- Dither. A value that specifies the dither setting of a view port. Dithering combines pixels of different colors to create the illusion of more colors than are actually supported by the hardware of an output device. For more information about the dither property, see the section "Dither" beginning on page 7-10.
- Halftone. A structure that specifies the halftone settings of the view port. Halftones use variable-sized dots of color to create the illusion of more colors than are actually supported by the hardware of an output device. For more information about the halftone property, see the section "Halftone" beginning on page 7-13.
- Parent view port. A reference to the view port that is the parent of this one. View ports exist in a hierarchial relationship that simplifies attaching them to windows and moving groups of them as units. For more information about the parent view port and view port hierarchies, see the section "Parent and Child View Ports" on page 7-18.
- Child view port list. A list of references to the view ports for which this view port is the immediate parent. View ports exist in a hierarchial relationship that simplifies attaching them to windows and moving groups of them as units. For more information about child view ports and view port hierarchies, see the section "Parent and Child View Ports" on page 7-18.
- View group. A reference to the view group object to which this view port belongs. View groups are described in the section "About View Group Objects" beginning on page 7-29.
- Attributes. A set of flags that affect various characteristics of the shapes drawn to this view port. See the section "View Port Attributes" on page 7-20 for more information.
- Tag list. A list of references to custom information about this view port object, stored in private structures called tag objects. The chapter "Tag Objects" in this book describes tag objects in general and how you can use them to add custom information to objects.
View Port Clip and Mapping
Like transform objects, view port objects have a clip property and a mapping property. A view port's mapping and clip are applied to a shape after the transform clip and mapping have already been applied.The clip and mapping properties for a view port follow the same general conventions as for transform objects. The clip property specifies a shape geometry that you use as a mask to restrict the visibility of a shape object when it is displayed or printed. The clip is equivalent to a primitive shape, a shape whose geometry and fill properties by themselves define the shape. Specifically, a clip can be a framed or filled geometric shape, a glyph shape, a 1-bit-per-pixel bitmap shape, or an empty or full shape. Primitive shapes are described in more detail in the geometric operations chapter of Inside Macintosh: QuickDraw GX Graphics.
The filled or framed parts of a view port clip define the areas in which a shape drawn to that view port show through. If the clip shape is a filled rectangle, for example, only the parts of a shape that are within the limits of that rectangle are visible. Commonly, view port clips are filled rectangles, because the visible parts of view ports commonly correspond to rectangular windows or panes of windows.
The mapping property of a view port is a 3 3 matrix that specifies one or more transformations that a view port applies to all shapes drawn into it. You can use the view port mapping to perform operations such as the following:
Most commonly, you use the view port mapping to position the view port (equivalent
- translation, which changes the positions of shapes in the view port
- scaling, which shrinks or enlarges shapes horizontally or vertically or both
- rotation, which turns shapes about a fixed point
- skewing, which distorts shapes progressively along a single axis
- perspective, which distorts shapes to provide a three-dimensional effect
to positioning a window), and possibly to scale or rotate its contents. Skewing and perspective are less common, but you can use them for special effects. You can specify the identity mapping, a matrix whose elements have the value 1.0 along the diagonal and 0.0 elsewhere, to leave shapes drawn to this view port unchanged from the application of the transform mapping.Figure 7-3 shows three different view ports in a single window, all used to display the same shape as that shown in Figure 7-1 on page 7-6. The shape is a vase, and its transform clip causes it to appear as wavy stripes.
Figure 7-3 Clipping and mapping in view ports
In Figure 7-3, each view port's clip shape is a rectangle that defines its pane in the window. The upper left view port uses an identity mapping. The lower left view port's mapping specifies a clockwise rotation. The right view port's mapping specifies scaling (equal in x and y dimensions) that enlarges the shape.
Dither
Dithering is a technique of assigning alternating colors to adjacent pairs or groups of pixels in a device's bitmap to achieve the illusion of a color that cannot be represented directly. For example, if a device only supports three shades of blue, dithering allows QuickDraw GX to assign those colors in a specific order to adjacent pixels, so that the mix of shades in the combined pixels approximates a desired but unsupported shade.Dithering works one way in shapes that have a uniform color, and another way in bitmaps.
Dithering of Shapes Other Than Bitmaps
The dither property of a view port specifies a dither level, which is the maximum number of colors that QuickDraw GX can use in dithering when it draws a shape. The dither level can be between 1 and 16; a dither level of 1, the simplest, is equivalent to no dithering. A level of 0 is not permitted. Dithering has no effect if the device resolution is 32 bits per pixel.Table 7-1 shows the pixel patterns that can occur, depending on the dither level. A dither level of 1 provides a solid pattern, which is effectively no dithering. A dither level of 2 provides a 2-by-2 repeating checkerboard pattern. A dither level of 3 provides a 3-by-3 repeating stripe pattern. A dither level of 4 provides a 4-by-2 repeating pattern. Note that the effective resolution of an image decreases as dither level increases, because each set of pixels that make up a unit of the dither pattern function as a single, larger pixel of dithered color.
QuickDraw GX does not necessarily use exactly the dither pattern specified by the
- Implementation Note
- Version 1.0 of QuickDraw GX supports a maximum of 16 colors in a dither pattern, although 4 is the practical maximum dither level, especially for grayscale drawing.
![]()
dither property, unless the ink object attached to the shape drawn to the view port has
itsgxForceDitherInk
attribute set. For example, if you specify a dither level of 4, QuickDraw GX may use any pattern from level 1 through level 4, as necessary, to
create the illusion of additional colors. If the ink object'sgxForceDitherInk
attribute is set, however, only the level-4 pattern is used. Conversely, if the ink
object'sgxSuppressDitherInk
attribute is set, no dithering occurs. Note also that
you can affect the pixel alignment of the dither pattern with the ink object'sgxPortAlignDitherInk
attribute. For more information about these ink attributes, see the chapter "Ink Objects" in this book.QuickDraw GX uses information from the color profile for the view device object to determine the supported colors and it chooses the appropriate colors to use in the dither for you. Although the results of dithering are controlled by the view device, you specify the dither level in the view port object so that you can simulate its effect, on the computer that is running the application, for a device that may not actually be present.
Dithering of Bitmaps
When you draw a bitmap shape, dithering works differently. Unlike with single-color shapes, dithering of bitmaps uses no specific pattern and recognizes no different dither levels. Dithering is off if the dither level is 1, and it is on if the dither level is greater than one.Dithering of bitmaps uses the process of error diffusion, in which the error (the difference between the computed color of a given pixel and the nearest color available on the view device) is passed to adjacent pixels. The dithering algorithm starts at the top left of the visible part of the bitmap, and progresses through the bitmap, traveling left to right across one row of pixels and then right to left across the next lower row, and so on until the entire bitmap has been traversed. For each pixel, the algorithm adds the accumulated error (passed from the pixel above it and the pixel to the left of it) to the computed color, picks the closest available device color for that pixel, and passes the new error (the new computed color minus the available color) to the pixel to the right and the pixel below; half of the error goes to each.
Not all dither-related ink attributes are applicable to dithering of bitmaps. Setting
or clearing thegxPortAlignDitherInk
attribute or thegxForceDitherInk
attribute of the ink object attached to a bitmap shape has no effect. Setting thegxSuppressDitherInk
attribute, however, does have the effect of turning off dithering, even for bitmaps.Ink attributes are described in the chapter "Ink Objects" in this book. The bitmap shapes chapter of Inside Macintosh: QuickDraw GX Graphics shows an example of drawing a dithered bitmap.
Drawbacks of Dithering
Dithering can provide good results in many cases, but it does have drawbacks:
Note that dithering and halftones (described next) are mutually exclusive; if you choose both simultaneously, only a halftone is used.
- Dithering slows down the drawing operation slightly for non-bitmap shapes, because of the overhead of determining the pattern in which colors are assigned. Dithering significantly slows down the drawing of bitmaps.
- You cannot reliably use an ink transfer mode to reverse the effect of drawing a color that is dithered. Thus, transfer modes such as highlight mode may not be completely reversible where dithering occurs.
- In bitmap dithering, because QuickDraw GX determines which color to apply to a pixel using the color of the pixel next to it, a cumulative dithering error can occur due to the way a preceding pixel is changed by the dithering algorithm.
- Because clipping can interrupt the error diffusion in a bitmap dither, dithering a clipped shape can produce a different result from dithering the same unclipped shape. It can also mean that redrawing portions of an image, as when scrolling, can cause seams, or visible lines, between the separately drawn portions.
Halftone
A halftone is a pattern of alternating colors of variable intensities in a fixed cell size, used to represent a variety of colors. Halftoning, like dithering, provides a method of representing color by alternating the available colors on view devices that support only a limited number of colors. Unlike a dither pattern, however, a halftone's fixed cell size means that its resolution is constant and adjacent halftones representing different colors mesh well. Also, unlike with dithers, you specify the colors that make up a halftone. If you use halftones, you should be familiar with how QuickDraw GX represents color, as described in the chapter "Color and Color-Related Objects" in this book. Also, note that dithering and halftones are mutually exclusive; if you choose both simultaneously, only a halftone is used.A halftone consists of a pattern of variable-sized dots of one color against a background of another color. The halftone simulates a desired color (such as a specific intensity of gray), with the proper proportion of dot color (such as black) and background color (such as white). The colors are not limited to single components, however; a halftone can simulate beige, for example, by mixing pink with yellow. QuickDraw GX can attempt to reproduce any desired color by mixing the dot color and background color specified in a halftone. You can specify any color as the background and any other color as the dot color, and QuickDraw GX will find the best mixing proportion, given the specifications that you provide. Commonly, however, if you are using halftones you work with a single color component (such as blue for RGB space or yellow for CMYK space), and you specify that component as the dot color and black (for RGB) or white (for CMYK) as the background color.
A halftone is described by several characteristics, specified in the
gxHalftone
structure:
struct gxHalftone{ Fixed angle; /* direction of halftone */ Fixed frequency; /* cells per inch */ gxDotType method; /* kind of pattern */ gxTintType tinting; /* tint calculation method*/ gxColor dotColor; /* color of dots */ gxColor backgroundColor; /* color of background */ gxColorSpace tintSpace; /* color space for tint */ };The angle describes the orientation of the rows of dots in the halftone pattern. It is a fixed-point number between 0.0 and 360.0 that describes an angle, in degrees, clockwise from horizontal. Figure 7-4 shows several angles.
Each cell in a halftone is an area that contains some proportion of background color and dot color. The frequency describes the size of the cells, in terms of numbers of dots per inch. You typically specify a frequency based on desired output quality and device resolution. Figure 7-5 shows examples of various frequencies.
The method, or dot type, describes the halftone pattern itself and how it is filled: the shapes of the dots, the pattern of their arrangement, and the way in which a dot fills its cell as it enlarges. The supported methods are defined in the
gxDotTypes
enumeration:
enum gxDotTypes{ gxRoundDot = 1, gxSpiralDot, gxSquareDot, gxLineDot, gxEllipticDot, gxTriangleDot, gxDispersedDot }; typedef long gxDotType;Figure 7-6 shows examples of these patterns.
The tinting, or tint type, specifies how the input color (the original color to which the halftone is applied) is to be approximated by a ratio of dot color and background color. The tint is a calculated value from zero to one: if the tint is zero, the halftone is composed only of the background color (the dots are infinitesimally small); if the tint is one, the halftone is composed entirely of the dot color (the dots fill their cells entirely). The tint color is the actual color represented by the combination of dot and background, and is therefore a weighted average of the dot color and background color. The tint color may be only an approximation to--or even just a single component of--the input color. The gxTintTypes enumeration, described on page 7-67, defines these tinting choices:
The dot color and background color are, respectively, the color of the dots and the color of the background used to form the halftone. In the halftone structure, they are full color specifications, not just single color-component values. In setting up a halftone structure, you need to specify these colors in a way that is meaningful considering the tint type you have chosen. For example, if you are creating a halftoned color separation, you typically use a dot color that is the same color as the color component specified in the tint type, and a background color of white.
- Luminance. The tint color is the input color's luminance. The gray closest to the luminance of the input color is used to calculate the tint value. This tinting method is used for making grayscale halftones from grayscale or color images.
- Color component. The tint color is some intensity of any one of the components of the input color. This tinting method is used for making halftoned color separations.
- Color average. The tint color is the average of the components of the input color, determined by adding up the color components and dividing them by the number of components. This tint type is used with RGB only, and follows this formula:
tint = 1 -- (R + G + B) / 3
Color average is different from luminance in that, for example, the luminance of an RGB color is not exactly the average of its component intensities. This tinting method is used for making grayscale halftones from color images.
- Color mixture. The tint color is a point on the line (in color space) connecting the dot color and the background color. The orthogonal projection of the input color onto that line locates the tint color, and the tint (the proportion of dot to background) is defined by the position of that projection point on the line. This is the formula:
tint = 1 -- D1 / (D1 + D2)
where
D1 = input color-dot color distance
D2 = input color-background color distance
This tinting method is used for getting the closest possible representation of any input color using any dot and background colors.
The tint space describes the color space the input color is converted to before the tint value is determined. For instance, you can set the tint space to CMYK space to separate out the cyan portion of an image that may have been created in RGB space. It is not necessary for the input colors or the view device colors to be set to CMYK space, only the halftone.
Note that halftoning occurs for a shape only if its view port contains a valid halftone structure, and if its ink object's gxSuppressHalftoneInk attribute is cleared. The gxSuppressHalftoneInk attribute is described in the chapter "Ink Objects" in this book.
Parent and Child View Ports
Two view port properties, the parent view port and the child view port list, allow you to arrange view ports in a hierarchy. The primary advantage of this capability is that QuickDraw GX manages the positional relationships among several related view ports for you.In a view port object, the hierarchical relationship is represented by parent and child view port references. Each view port can reference one parent view port and any number of child view ports. When you move a view port by altering its clip and mapping, QuickDraw GX moves all its child view ports (and their child view ports, if any) accordingly. If the parent view port of your view port is attached to a window, QuickDraw GX moves your view port (and its children) to match movements of the parent whenever the user moves the window.
A view port hierarchy consists of a root view port, which is one with no parent view port, and all of its child view ports. If a child view port is also a parent view port, its children are part of the hierarchy too, and so on. Any parent view port in a hierarchy also defines a subhierarchy that consists of itself as the root, its child view ports, their child view ports, and so on.
Consider, for example, the window shown in Figure 7-7. Like in Figure 7-3 on page 7-10, it displays three different views of a vase. In this case, however, all the views are scrollable, which requires four view ports in a hierarchy.
Figure 7-7 Hierarchical view ports in a window
The four view ports associated with the window in Figure 7-7 are arranged in the simple hierarchy shown in Figure 7-8.
Figure 7-8 A view port hierarchy
View port A encompasses the entire content area of the window. It does not have a parent, so it is the root of the hierarchy. View port A has three child view ports: B, C,
and D. View ports B, C, and D all have the same parent, view port A. None of them, however, have child view ports of their own.This hierarchial organization allows QuickDraw GX to automatically move all view ports when the window is moved. It also allows you to support scrolling in view port B, C, or D with minimal effort. When the user scrolls pane B, for example, the translation in view port B's mapping is changed to reflect the shape's new position in the window. No changes are required to the other child view ports or to view port A to implement scrolling. See the section "View Port Objects and Windows" beginning on page 7-21 for more information on view port hierarchies and windows.
When you set up a view port hierarchy, you create the root view port by calling the
GXNewWindowViewPort
function if you want the view port to be associated with a window, or theGXNewViewPort
function otherwise. You create child view ports by calling theGXNewViewPort
function for each, and then using theGXSetViewPortParent
andGXSetViewPortChildren
functions to organize them into a hierarchy.The following rules apply when you set up a view port hierarchy:
- You cannot create a circular relationship among view ports. For example, a parent view port cannot also be a child view port within its own hierarchy.
- The view ports in a hierarchy must all be in the same view group.
View Port Attributes
Each view port object has a set of attributes, a group of flags that specify different aspects of display behavior. View port attributes allow you to specify drawing in gray only, to constrain shapes to integral pixel locations, or to enable color matching for shapes drawn to the port. Table 7-2 lists the constants for the view port attribute and describes what each one means. The constants are defined in thegxPortAttributes
enumeration.